package com.liaoyifan.core.util;

import com.liaoyifan.core.exception.CoreException;
import com.liaoyifan.core.function.Running;
import com.liaoyifan.core.function.Supplying;
import com.liaoyifan.core.opera.GlobalExceptionHandler;
import com.liaoyifan.core.valid.Lang;
import java.util.function.Function;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;

@NoArgsConstructor(access = AccessLevel.PRIVATE)
@SuppressWarnings("unused")
public final class Try {

    public static void run(Running running) {
        run(
                () -> {
                    running.run();
                    return null;
                },
                null);
    }

    public static void run(Running running, Runnable complete) {
        run(
                () -> {
                    running.run();
                    return null;
                },
                complete);
    }

    public static <T> T run(Supplying<T> supplying) {
        return run(supplying, null);
    }

    public static <T> T run(Supplying<T> supplying, Runnable complete) {
        return run(supplying, null, complete);
    }

    public static <T> T run(
            Supplying<T> supplying,
            Function<Throwable, RuntimeException> exception,
            Runnable complete) {
        try {
            return supplying.get();
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            throw new RuntimeException(e);
        } catch (CoreException e) {
            throw e;
        } catch (Throwable e) {
            if (exception != null) {
                throw exception.apply(e);
            }
            throw new RuntimeException(e);
        } finally {
            if (complete != null) {
                complete.run();
            }
        }
    }

    public static String log(String message, Throwable e, Object... data) {
        if (e == null) return "";

        // 获取根因异常（带循环引用保护）
        Throwable rootCause = e;
        while (rootCause.getCause() != null && rootCause.getCause() != rootCause) {
            rootCause = rootCause.getCause();
        }

        // 获取当前异常信息
        String currentType = e.getClass().getName();
        String currentLocation = getLocation(e.getStackTrace());
        String currentMsg = String.valueOf(message);

        if (Lang.isNotEmpty(data)) {
            currentMsg += " - " + Json.toString(data.length == 1 ? data[0] : data);
        }

        // 获取根因信息
        String rootType = rootCause.getClass().getName();
        String rootLocation = getLocation(rootCause.getStackTrace());
        String rootMsg = String.valueOf(rootCause.getMessage());

        // 结构化日志
        if (e == rootCause) {
            GlobalExceptionHandler.log.warn(
                    "[{}] at {}: {}", currentType, currentLocation, currentMsg);
        } else {
            GlobalExceptionHandler.log.warn(
                    "[{}] at {}: {} -> [{}] at {}: {}",
                    currentType,
                    currentLocation,
                    currentMsg,
                    rootType,
                    rootLocation,
                    rootMsg);
        }
        return message;
    }

    private static String getLocation(StackTraceElement[] stack) {
        if (stack != null && stack.length > 0) {
            StackTraceElement frame = stack[0];
            return String.format(
                    "(%s.%s:%d)",
                    frame.getClassName(), frame.getMethodName(), frame.getLineNumber());
        }
        return "UnknownLocation";
    }
}
